<template>
    <div class="approval-history-box">
        <div class="title">
            {{ t('log') }}
        </div>
        <a-timeline>
            <a-timeline-item>
                <template #dot>
                    <span class="start"></span>
                </template>
                {{ t('start') }}
            </a-timeline-item>
            <div
                v-for="(approveTaskListGroupItem, index) in approveTaskListGroup"
                :key="index"
                :ref="
                    el => {
                        if (el) divs[`time-line-bottom-${i}`] = el
                    }
                "
                :class="{ group: approveTaskListGroupItem.children.length > 1 }"
            >
                <div v-if="approveTaskListGroupItem.children.length" class="group-mark"></div>
                <div v-for="(item, approveTaskIndex) in approveTaskListGroupItem.children" :key="approveTaskIndex">
                    <a-timeline-item>
                        <template #dot>
                            <div class="avatar" :style="item.avatarColor">
                                {{ item.operatorName[0] }}
                            </div>
                        </template>
                        <div class="approval-history-content">
                            <h5 class="title">
                                <check-circle-filled
                                    v-if="['APPROVED', 'REVOKE'].includes(item.status)"
                                    class="check-circle"
                                />
                                <close-circle-filled v-else-if="item.status === 'REJECT'" class="close-circle" />
                                <stop-filled v-else-if="item.status === 'ROLLBACK'" class="close-circle" />
                                {{ item.title }}
                            </h5>
                            <p v-if="!isNullOrEmpty(item.time)" class="time">
                                {{ item.time }}
                            </p>
                            <p v-if="item.comment" class="comment">
                                {{ item.comment }}
                            </p>
                        </div>
                    </a-timeline-item>
                </div>
                <a
                    v-if="approveTaskListGroupItem.btnText"
                    class="open"
                    @click="setMoreOrLessHandler(approveTaskListGroupItem, index)"
                    >{{ approveTaskListGroupItem.btnText }}</a
                >
            </div>
        </a-timeline>
    </div>
</template>

<script lang="ts">
    import { defineComponent, ref, watch, nextTick, onBeforeUpdate } from 'vue'
    import { useI18n } from 'vue-i18n'
    import { isNullOrEmpty } from '@/utils/is'
    import { formatDataType, approveTaskListItem } from '../types/index'
    export default defineComponent({
        name: 'ApprovalHistory',
        props: {
            approveTaskList: {
                type: Array,
                default: () => []
            }
        },
        setup(props) {
            const { t } = useI18n()
            const divs = ref([])
            // 演示用图标及颜色
            const FAKE_ICON = {
                icon: [
                    'book',
                    'bulb',
                    'build',
                    'crown',
                    'experiment',
                    'carry-out',
                    'fire',
                    'flag',
                    'compass',
                    'dashboard'
                ],
                color: [
                    '#2d8cf0',
                    '#19be6b',
                    '#5cadff',
                    '#ff9900',
                    '#17233d',
                    '#2db7f5',
                    '#ed4014',
                    '#dcdee2',
                    '#515a6e',
                    '#808695'
                ]
            }
            const approveTaskListGroup = ref<formatDataType[]>([])
            const max = ref(3) // 分组默认最大显示数据条数
            function formatData(groupItem: approveTaskListItem[]) {
                // 为显示的时间线数据增加字段,用于判断是否显示
                const groupItemData = groupItem.map(item => {
                    item.title = getTitle(item)
                    item.time = getInitStatus(item) ? item.endTime : item.beginTime
                    item.comment = item.comment ? `${t(`comment`)}${t('colon')}${item.comment}` : ''
                    return item
                })
                const newData: formatDataType = {
                    originData: groupItemData, // 数据真正的长度
                    children: groupItemData.slice(0, max.value) // 需要展示的数据的, 分组时, 默认最多展示3条
                }
                newData.btnText = getBtnText(newData)
                return newData
            }
            /**
             * 按钮展示的文本['收起', '展开']
             */
            function getBtnText(groupItemData) {
                if (groupItemData.originData.length <= max.value) {
                    return ''
                }
                return groupItemData?.originData.length > groupItemData?.children.length ? t('openMore') : t('less')
            }
            /**
             * 流程是否是发起状态, 目前发起状态是null, 影响标题显示,时间显示
             */
            function getInitStatus(item) {
                return item.status
            }
            /**
             * 时间线,标题差异化显示
             */
            function getTitle(item) {
                let title = ''
                if (getInitStatus(item)) {
                    // 流程中的状态
                    title = `${item.taskName ? `${item.taskName} - ` : ''}${item.operatorName}`
                } else {
                    // 初始状态
                    title = `发起人 - ${item.operatorName}`
                }
                return title
            }
            /**
             * 对接口返回的数据根据字段approveNodeKey进行分组
             * 1. 要求按照数据的顺序进行分组
             * 2. 根据approveNodeKey分组
             * 因为流程日志有回退的情况,approveNodeKey不能完全实现分组的情况,后台控制确保数据的顺序
             * 相邻的数据根据approveNodeKey分组
             */
            function getApproveTaskListGroup() {
                // 用于生成新的二维数组
                const groupArr = [] as formatDataType[]
                // 用于判断是否是一组的Key
                let preKey = ''
                // 提前定义的每一小分组的数据
                let groupItem = [] as approveTaskListItem[]
                props.approveTaskList.forEach((approveTaskItem: approveTaskListItem, approveTaskItemIndex) => {
                    approveTaskItem.avatarColor = setAvatarColor(approveTaskItemIndex)
                    if (approveTaskItem.approveNodeKey !== preKey) {
                        // 小分组的数据组装完成, 推入groupArr, 并清空小分组数据继续收集下一个分组
                        groupArr.push(formatData(groupItem))
                        groupItem = [approveTaskItem]
                    } else {
                        /*
                         * 收集小分组数据
                         * 如果是进行回退,那么后台返回的数据是包括"审批中"的数据,该数据无须显示,通过operatorId过滤
                         */
                        groupItem = groupItem.filter(item => item.operatorId !== approveTaskItem.operatorId)
                        groupItem.push(approveTaskItem)
                    }
                    // 逻辑执行之后把当前的key赋值preKey用于下一个循环的判断
                    preKey = approveTaskItem.approveNodeKey
                })
                // 循环完毕,把最后制作分组数据推入groupArr
                if (groupItem.length > 0) {
                    groupArr.push(formatData(groupItem))
                }
                approveTaskListGroup.value = groupArr
                nextTick(() => {
                    // 时间线最后一个元素滚动到可视区域
                    const [groupRef] = divs.value[`time-line-bottom-${groupArr.length - 1}`] || []
                    groupRef?.scrollIntoView()
                })
            }
            function setAvatarColor(index) {
                return { backgroundColor: FAKE_ICON.color[index % FAKE_ICON.color.length] }
            }
            /**
             * 按钮 展开/收起 点击后执行的逻辑
             */
            function setMoreOrLessHandler(approveTaskListGroupItem, index) {
                if (approveTaskListGroupItem.originData.length > approveTaskListGroupItem.children.length) {
                    approveTaskListGroupItem.children = approveTaskListGroupItem.originData
                } else {
                    approveTaskListGroupItem.children = approveTaskListGroupItem.originData.slice(0, max.value)
                }
                approveTaskListGroupItem.btnText = getBtnText(approveTaskListGroupItem)
                approveTaskListGroup.value[index] = approveTaskListGroupItem
            }
            watch(
                () => props.approveTaskList,
                () => getApproveTaskListGroup(),
                {
                    immediate: true
                }
            )
            // 确保在每次更新之前重置ref
            onBeforeUpdate(() => {
                divs.value = []
            })
            return {
                t,
                divs,
                isNullOrEmpty,
                approveTaskListGroup,
                setMoreOrLessHandler
            }
        }
    })
</script>

<style lang="less" scoped>
    .approval-history-box {
        overflow: auto;
        padding: 36px 24px 24px 36px;

        & > .title {
            font-size: 16px;
            color: #192842;
            line-height: 60px;
        }

        .start {
            display: inline-block;
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background: #6b98ff;
        }

        .avatar {
            width: 27px;
            height: 27px;
            border-radius: 50%;
            line-height: 27px;
            text-align: center;
            font-weight: bold;
            color: #fff;
            font-size: 12px;
        }

        :deep(.@{ant-prefix}-timeline-item-content) {
            font-size: 12px;
        }

        :deep(.@{ant-prefix}-timeline-item:first-child) {
            padding-bottom: 40px;

            .@{ant-prefix}-timeline-item-content {
                top: -2px;
            }
        }

        .approval-history-content {
            margin-left: 1em;

            p {
                margin: 0;
                line-height: 2em;
            }

            .title {
                font-size: 14px;
                display: flex;
                align-items: center;

                .svg-icon,
                i {
                    margin-right: 5px;
                }
            }

            .comment {
                font-size: 10px;
                padding-right: 30px;
                word-break: break-all;
            }
        }
    }

    .check-circle {
        color: #52c41a;
    }

    .close-circle {
        color: #d73a3b;
    }

    .group {
        position: relative;
        margin: 10px 0;

        .group-mark {
            left: -20px;
            top: -20px;
            height: 100%;
            width: 100%;
            position: absolute;
            background: #f5f5f5;
            border: 1px solid #bcc1c8;
        }

        .open {
            font-size: 12px;
            color: #3875ff;
            line-height: 36px;
            transform: translate(20px) translateY(-30px);
            display: block;
        }
    }

    :deep(.@{ant-prefix}-timeline-item-head-custom) {
        background: rgba(0, 0, 0, 0);
    }
</style>

<i18n>
zh-CN:
  start: 流程开始
  log: 流程日志
  openMore: 展开
  less: 收起
  comment: 留言
  colon: ：
en-US:
  start: Process start
  log: Process log
  openMore: open
  less: Put away
  comment: Leaving a message.
  colon: ：
</i18n>
